import { saveAs } from 'file-saver';

function parseNDArray(str, complexQuotation = '"') {
  str = str.trim().replace(/\s/g, ' ');
  if (str) {
    let result = '' + str[0];
    for (let prev = 0, cur = 1; cur < str.length; prev++, cur++) {
      if (str[prev] !== ' ' || str[cur] !== ' ') {
        if (str[prev]) { result += str[cur]; }
      }
    }
    result = result.replace(/(\[ | \])/g, function(str) {
      if (str[0] === '[') {
        return str[0];
      } else return str[1];
    });
    result = result.replace(/(\]) /g, '$1,');

    var numRe = /[-+]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][-+]?[0-9]+)?(?!\s?[-+]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][-+]?[0-9]+)?j)[\s\]]/g;
    var complexRe = /(nan|inf|(([-+]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][-+]?[0-9]+)?|nan|inf)\s?[-+]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][-+]?[0-9]+)?j))[\s\]]/g;

    // 匹配复数
    result = result.replace(complexRe, function(str) {
      const tmp = str[str.length - 1];
      str = complexQuotation + str.substring(0, str.length - 1) + complexQuotation;
      const tail = tmp === ']' ? '' : ',';
      return str + tail + tmp;
    });
    // 匹配普通数字, 但不匹配复数中的数字
    result = result.replace(numRe, function(str) {
      const tmp = str[str.length - 1];
      str = str.substring(0, str.length - 1);
      const tail = tmp === ']' ? '' : ',';
      if (str[str.length - 1] === '.') {
        str = str.substring(0, str.length - 1) + tail;
      } else {
        str = str + tail;
      }
      return str + tmp;
    });
    return result;
  }
  return str;
}

export const unserialize = function(variableArray) {
  let str = variableArray.length > 0 ? '\timport numpy as np\n' : '';
  for (const variable of variableArray) {
    const skipTypes = ['function', 'dict', 'module', 'object', 'class', 'set'];
    if (skipTypes.includes(variable['Type'])) {
      continue;
    }
    if (variable['Type'].includes('Array of ')) {
      const parsed = parseNDArray(variable.Value, '');
      try {
        JSON.parse(parsed);
        let tmp = `${variable.Name} = np.array(${parsed})`;
        tmp = tmp.replace(/(nan|inf)(\s?[-+]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][-+]?[0-9]+)?j)?/g, 'np.$1$2');
        str = str + '\t' + tmp + '\n';
      } catch (err) {
        console.log(err);
      }
    } else if (variable.Type === 'str') {
      let value = variable.Value;
      value = value.replaceAll('\\', '\\\\');
      value = value.replaceAll('\'', '\\\'');
      value = value.replaceAll('\"', '\\\"');
      value = value.replaceAll('\n', '\\n');
      value = value.replaceAll('\t', '\\t');
      value = value.replaceAll('\r', '\\r');
      value = value.replaceAll('\b', '\\b');
      str = str + '\t' + `${variable.Name} = '${value}'\n`;
    } else {
      try {
        // 在这个分支里如果能通过JSON.parse, 说明可以插入该变量，否则跳过
        JSON.parse(variable.Value);
        str = `${str}\t${variable.Name} = ${variable.Value}\n`;
      } catch {
        continue;
      }
    }
  }
  return str;
};

export const processVar = function(variableArray) {
  const result = [];
  const arrayLikeType = ['NDArray', 'MaskedArray', 'Matrix', 'Array of '];
  for (const variable of variableArray) {
    if (variable['Type'] === 'module' || variable['Type'] === 'function') { continue; }
    let isArrayLikeType = false;
    for (const Type of arrayLikeType) {
      if (variable['Type'].includes(Type)) {
        isArrayLikeType = true;
      }
    }
    // 防止修改原来variableArray里面的variable
    const copy = Object.assign({}, variable);
    copy.tooLong = variable.Value.length >= 16;
    let value = variable.Value;
    let show = 'plain';
    let ellipsis;
    if (copy.tooLong) {
      if (isArrayLikeType) {
        let shape = variable['Size'].replace(/\s/g, '').slice(1, -1); // 去掉空白符号和括号
        if (shape[shape.length - 1] === ',') {
          shape = shape.slice(0, -1);
        }
        const dimension = shape.split(',').length; // (5,5) -> 2, (5,) -> 1, (5,5,5) -> 3
        const type = variable['Type'].replace(/Array of /g, '');
        if (dimension <= 2) {
          let temp;
          try {
            temp = JSON.parse(parseNDArray(variable.Value));
            if (dimension === 2) {
              value = temp;
            } else {
              const arr = [];
              arr.push(temp);
              value = arr;
            }
            show = 'matrix';
          } catch (err) {
            show = 'plain';
            value = variable.Value;
          }
          if (dimension === 2) {
            ellipsis = shape.replace(/,/g, 'x') + ' ' + type;
          } else {
            ellipsis = '1x' + shape + ' ' + type;
          }
        } else {
          ellipsis = variable['Size'].replace(/\s/g, '').split(',').length + '-D ' + type;
          show = 'plain';
          value = variable.Value;
        }
      } else {
        ellipsis = variable.Value.slice(0, 15) + '...';
        if (copy['Type'] === 'dict' || copy['Type'] === 'list') {
          try {
            let str = variable.Value.replace(/'/g, '"');
            str = str.replace(/False/g, 'false');
            str = str.replace(/True/g, 'true');
            const json = JSON.parse(str);
            show = 'json';
            value = json;
          } catch (err) {
            console.log(err);
          }
        }
      }
    }
    copy.value = value;
    copy.ellipsis = ellipsis;
    copy.show = show;
    copy.id = copy.Name;
    result.push(copy);
  }
  return result;
};

export const saveWorkspace = async(variable) => {
  try {
    const blob = new Blob([JSON.stringify(variable, null, '\t')]);
    saveAs(blob, 'variable.json');
  } catch (err) {
    console.error(err);
  }
  // try {
  //   const fileSystemFileHandle = await window.showSaveFilePicker({
  //     suggestedName: 'variable.json',
  //     types: [
  //       {
  //         description: 'Json',
  //         accept: {
  //           'application/json': '.json'
  //         }
  //       }
  //     ]
  //   });
  //   const writable = await fileSystemFileHandle.createWritable();
  //   await writable.write(JSON.stringify(variable, null, '\t'));
  //   await writable.close();
  //   this.$message.success('变量保存成功');
  // } catch (e) {
  //   console.log(e);
  // }
};
